#define LOG_TAG "CONNECTIVITY_HAL"
#define LOG_NDEBUG 0
#define LOG_NIDEBUG 0
#define LOG_NDDEBUG 0

#include <log/log.h>

#include "Connectivity.h"
#include "OpESIMConnectionStatus.h"
#include "OpSyncTCAMinformation.h"
#include "OpWLANAPConnDevList.h"
#include "OpWLANAPSETTING.h"
#include "OpWLANLOGSETTING.h"
#include "OpWLANLOGSETTINGReq.h"
#include "OpWLANMode.h"
#include "OpWLANModeReq.h"
#include "OpWLANSTAConnect.h"
#include "OpWLANSTADisCon.h"
#include "OpWLANSTAForgetRememberedNetwk.h"
#include "OpWLANSTARememberedNetwks.h"
#include "OpWLANSTAScan.h"
#include "OpWLANSTAStatus.h"
#include "CommonElements.h"
#include "OpTestConnectionStatus.h"
#include "OpNetworkConnectionStatus.h"
#include "OpSet5GMode.h"
#include "Op5GModeReq.h"

#include <vendor/ecarx/xma/connectivity/1.0/IConnectivity.h>
#include <vendor/ecarx/xma/connectivity/1.0/IConnectivityCallback.h>

namespace vendor
{
namespace ecarx
{
namespace xma
{
namespace connectivity
{
namespace V1_0
{
namespace implementation
{

void *cookie;
WifiState STA_state = WifiState::UNKNOWN;
SoftApState AP_state = SoftApState::UNKNOWN;

milliseconds common_delay = 10ms;
uint16_t Connectivity_OperationIDs[17] = {OP_ID_OpESIMConnectionStatus, OP_ID_OpWLANMode,
                                          OP_ID_OpWLANAPSETTING, OP_ID_OpWLANAPConnDevList,
                                          OP_ID_OpWLANSTAConnect, OP_ID_OpWLANSTAStatus,
                                          OP_ID_OpWLANSTARememberedNetwks, OP_ID_OpWLANSTAForgetRememberedNetwk,
                                          OP_ID_OpWLANSTAScan, OP_ID_OpWLANLOGSETTING,
                                          OP_ID_SyncTCAMinformation, OP_ID_OpWLANModeReq,
                                          OP_ID_OpWLANLogSettingReq, OP_ID_OpWLANSTADisCon,
                                          OP_ID_TestConnectionStatus, OP_ID_5GModeReq, OP_ID_Set5GMode};

void ipcp_error_cb(ipcp_packet_t *ipcp_packet, ipcp_stack_err_t error);
void wifi_ipcp_cb(ipcp_packet_t *packet, ipcp_peer_t peer);

ipcp_callbacks_t wifi_ipcp_callbacks = {
        .ipcp_received_cb = wifi_ipcp_cb,
        .error_cb = ipcp_error_cb,
};

static ipcp_peer_t wifi_tcam_ipcp_peer = {
        .sk_type = IPCP_TRANSPORT_UDP,
        .peer_ip = PEER_IP,
        .peer_port = SERVICE_PEER_PORT,
};

void init_ipcp_config(ipcp_transport_conf_t *config)
{
    config->service_id = SERVICE_ID_CONNECTIVITY;
    strcpy(config->host_ip, LOCAL_IP);
    config->host_port = SERVICE_LOCAL_PORT;
    config->sk_type = IPCP_TRANSPORT_UDP;
    config->vlan = SERVICE_VLAN_ID;
    config->priority = SERVICE_VLAN_PCP;
}

Connectivity::Connectivity() : mCallbackDeathRecipient(new DeathRecipient(this))
{
    ALOGD("%s", __func__);
    cookie = this;
}

Connectivity::~Connectivity()
{
    ALOGD("%s", __func__);
    if (mCallback != nullptr) {
        mCallback->unlinkToDeath(mCallbackDeathRecipient);
        mCallback = nullptr;
    }
}

void Connectivity::onFirstRef() {
    ALOGI("%s", __func__);
    setup_wifi_ipcp();
}

void Connectivity::setupVehicle() {
    bool vehicle_ready = false;

    ALOGI("%s: Connecting to Vehicle HAL", __func__);
    if (mVehicle != nullptr) {
        ALOGD("%s: Vehicle Interface already initialized", __func__);
        return;
    }

    while (!vehicle_ready) {
        if (mVehicle == nullptr)
            mVehicle = IVehicle::tryGetService();

        if (mVehicle != nullptr) {
            if (mVehicle.get() != nullptr) {
                vehicle_ready = true;
                break;
            }
        }

        ALOGE("%s: try get Vehicle Service failed, will try again 500ms later", __func__);
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }
    ALOGI("%s: Connected to Vehicle HAL successfully", __func__);
}

bool Connectivity::setValue(VehiclePropValue setProp) {
    Automotive_StatusCode status = Automotive_StatusCode::TRY_AGAIN;

    if (mVehicle == nullptr || mVehicle.get() == nullptr) {
        ALOGE("%s, mVehicle is NULL", __func__);
        return false;
    }

    status = mVehicle->set(setProp);

    if (status == Automotive_StatusCode::OK) {
        ALOGI("%s, set VehicleProp %#x success", __func__, setProp.prop);
        return true;
    } else {
        ALOGE("%s: failed with status %d", __func__, status);
        return false;
    }
}

void Connectivity::setIncompatibleIpcpDtc() {
    /*VehiclePropValue val({
        .prop = static_cast<int32_t>(VendorVehicleProperty::CB_AP_D08100_Incompatible_IP_bus_Signal_Received_From_TCAM),
        .areaId = 1,
        .status = VehiclePropertyStatus::AVAILABLE,
        .timestamp = 0,
        .value.int32Values = std::vector<int32_t>{ 0 }
    });

    val.value.int32Values[0] = 2;
    ALOGD("%s: set connectivity_vehicle_set_CB_AP_D08100_Incompatible_IP_bus_Signal_Received_From_TCAM", __func__);

    setValue(val);*/
}

void Connectivity::handleHidlDeath() {
    ALOGD("%s", __func__);
    if (mCallback != nullptr) {
        mCallback->unlinkToDeath(mCallbackDeathRecipient);
        mCallback = nullptr;
    }
}

Return<StatusCode> Connectivity::registerIConnectivityCallback(const sp<IConnectivityCallback>& callback) {
    lock_guard<mutex> lk(mMut);
    StatusCode ret = StatusCode::FAILED;
    if (mCallback == nullptr) {
        mCallback = callback;
        mCallback->linkToDeath(mCallbackDeathRecipient, 0);
        ret = StatusCode::SUCCESS;
    }
    return ret;
}

Return<StatusCode> Connectivity::unregisterIConnectivityCallback(const sp<IConnectivityCallback>& callback) {
    ALOGI("%s", __func__);
    lock_guard<mutex> lk(mMut);
    StatusCode ret = StatusCode::FAILED;
    if(mCallback != nullptr)
    {
        mCallback->unlinkToDeath(mCallbackDeathRecipient);
        mCallback = NULL;
        ret = StatusCode::SUCCESS;
    }
    return ret;
}

sp<Connectivity> Connectivity::getConnectivity(void *cookie)
{
    wp<Connectivity> weak(reinterpret_cast<Connectivity *>(cookie));
    sp<Connectivity> conn = weak.promote();
    return conn;
}

sp<IConnectivityCallback> Connectivity::getCallback()
{
    if (mCallback != nullptr) {
        return mCallback;
    }

    return nullptr;
}

void ipcp_error_cb(ipcp_packet_t *ipcp_packet, ipcp_stack_err_t error)
{
    ipcp_header_t *header = &ipcp_packet->header;
    uint16_t len = header->length - ASN_HEADER_LENGTH_OFFSET;

    sp<Connectivity> conn = Connectivity::getConnectivity(cookie);
    sp<IConnectivityCallback> callback = conn->getCallback();

    ALOGI("recv error_cb... %d", error);
    switch(error)
    {
        case STACK_FAILURE_CREATE_SOCKET:
        case STACK_FAILURE_SET_VLAN:
        case STACK_FAILURE_BIND_SOCKET:
        case STACK_FAILURE_LISTEN_SOCKET:
        case STACK_FAILURE_ACCEPT_SOCKET:
        case STACK_FAILURE_CONNECT_SOCKET:
        case STACK_FAILURE_CREATE_THREAD: {
            ipcp_cleanup();
            sleep(2);
            conn->setup_wifi_ipcp();
            break;
        }
        case STACK_FAILURE_WFA_TIMEOUT:
        case STACK_FAILURE_WFR_TIMEOUT: {
            ALOGE("STACK_FAILURE_WFA_TIMEOUT");
            if (callback == nullptr) {
                ALOGE("%s, callback is NULL, will not callback upper layer", __func__);
                return;
            }

            switch (header->operation_id)
            {
            case OP_ID_OpWLANMode:
                if (STA_state == WifiState::DISABLING) {
                    callback->onIPCPErrorCallback(ConnIPCPOperation::WLANMode, ErrorCode::STA_STOP_FAILED);
                } else if (STA_state == WifiState::ENABLING) {
                    callback->onIPCPErrorCallback(ConnIPCPOperation::WLANMode, ErrorCode::STA_START_FAILED);
                }

                if (AP_state == SoftApState::ENABLING) {
                    callback->onIPCPErrorCallback(ConnIPCPOperation::WLANMode, ErrorCode::SoftAP_START_FAILED);
                } else if (AP_state == SoftApState::DISABLING) {
                    callback->onIPCPErrorCallback(ConnIPCPOperation::WLANMode, ErrorCode::SoftAP_STOP_FAILED);
                }
                break;

            case OP_ID_OpWLANAPSETTING:
                callback->onIPCPErrorCallback(ConnIPCPOperation::WLANAPSetting, ErrorCode::SoftAP_SET_Config_FAILED);
                break;
            case OP_ID_OpWLANAPConnDevList:
                callback->onIPCPErrorCallback(ConnIPCPOperation::WLANAPConnDevList, ErrorCode::SoftAP_Query_Clients_FAILED);
                break;
            case OP_ID_OpWLANSTAConnect:
                callback->onIPCPErrorCallback(ConnIPCPOperation::WLANSTAConnect, ErrorCode::STA_CONNECT_FAILED);
                break;
            case OP_ID_OpWLANSTARememberedNetwks:
                callback->onIPCPErrorCallback(ConnIPCPOperation::WLANSTARememberedNetwks, ErrorCode::STA_GET_Network_FAILED);
                break;
            case OP_ID_OpWLANSTAForgetRememberedNetwk:
                callback->onIPCPErrorCallback(ConnIPCPOperation::WLANSTAForgetRememberedNetwk, ErrorCode::STA_FORGET_FAILED);
                break;
            case OP_ID_OpWLANSTAScan:
                callback->onIPCPErrorCallback(ConnIPCPOperation::WLANSTAScan, ErrorCode::STA_SCAN_FAILED);
                break;
            case OP_ID_OpWLANLOGSETTING:
            case OP_ID_OpWLANLogSettingReq:
                callback->onIPCPErrorCallback(ConnIPCPOperation::WLANLOGSETTING, ErrorCode::SET_TCAM_LOG_S_FAILED);
                break;
            case OP_ID_SyncTCAMinformation:
                callback->onIPCPErrorCallback(ConnIPCPOperation::SyncTCAMinformation, ErrorCode::QUERY_TCAM_INFORMATION_FAILED);
                break;
            case OP_ID_OpWLANModeReq:
                if (callback != nullptr)
                    callback->onIPCPErrorCallback(ConnIPCPOperation::WLANModeReq, ErrorCode::QUERY_CurrentMode_FAILED);
                break;
            case OP_ID_OpWLANSTADisCon:
                callback->onIPCPErrorCallback(ConnIPCPOperation::WLANSTADisCon, ErrorCode::STA_DISCONNECT_FAILED);
                break;
            case OP_ID_TestConnectionStatus:
                callback->onIPCPErrorCallback(ConnIPCPOperation::TestConnectionStatus, ErrorCode::TEST_CONNECTION_STATUS_FAILED);
                break;
            case OP_ID_NetworkConnectionStatus:
                callback->onIPCPErrorCallback(ConnIPCPOperation::NetworkConnectionStatus, ErrorCode::NETWORK_CONNECTION_STATUS_FAILED);
                break;
            case OP_ID_5GModeReq:
                ALOGE("%s, unknown 5GModeReq", __func__);
                break;
            case OP_ID_Set5GMode:
                ALOGE("%s, unknown Set5GMode", __func__);
                break;
            default:
                ALOGE("%s, unknown WFA/WFR TMO", __func__);
                break;
            }
            break;
        }
        case DIAG_ERROR_Code_Invalid_Protocl_Version:
        case DIAG_ERROR_CODE_SERVICE_ID_NOT_AVAILABLE:
        case DIAG_ERROR_Code_OperationID_Not_Available:
        case DIAG_ERROR_Code_OperationType_Not_Available:
        case DIAG_ERROR_Code_Invalid_Length: {
            ALOGE("Invalid IPCP patcket, report DTC");
            conn->setIncompatibleIpcpDtc();
            break;
        }
        default: {
            ALOGE("%s, unknown error", __func__);
            break;
        }
    }
}

IpAddress handleIpAddress(const int count, const OSOCTET data[]) {
    IpAddress ipAddr;
    string str;
    ipAddr.num = count;
    for (auto i = 0; i < count; i++) {
        str.append(std::to_string(data[i]));
        if (i != (count -1)) {
            str.append(".");
        }
    }
    ipAddr.addr = str;
    return ipAddr;
}

void handleGenericError(ipcp_packet_t *packet, uint32_t oper_id) {
    ALOGE("%s, decode error %d", __func__, oper_id);
    ipcp_header_t *header = &packet->header;
    uint16_t len = header->length - ASN_HEADER_LENGTH_OFFSET;

    ASN1PERDecodeBuffer decodeBuffer((OSOCTET *)packet->payload, len, false);
    ASN1T_OpGeneric_Error data;
    ASN1C_OpGeneric_Error OpGeneric_Error(decodeBuffer, data);
    if (OpGeneric_Error.Decode()) {
        ALOGE("%s, decode error", __func__);
    } else {
        sp<Connectivity> conn = Connectivity::getConnectivity(cookie);
        sp<IConnectivityCallback> callback = conn->getCallback();

        if (callback != nullptr) {
            callback->onIPCPErrorCallback(static_cast<ConnIPCPOperation>(oper_id),
                    static_cast<ErrorCode>(data.errorCode));
        }
    }
}

void handleESIMConnectionStatus(ipcp_packet_t *packet) {
    if (packet == nullptr) return;

    ipcp_header_t *header = &packet->header;
    uint16_t len = header->length - ASN_HEADER_LENGTH_OFFSET;

    switch (header->op_type) {
        case OP_TYPE_NOTIFICATION_CYCLIC: {
            ASN1PERDecodeBuffer decodeBuffer((OSOCTET *)packet->payload, len, false);
            ASN1T_OpESIMConnectionStatus_NotificationCyclic data;

            ASN1C_OpESIMConnectionStatus_NotificationCyclic OpESIMConnectionStatus(decodeBuffer, data);
            if (OpESIMConnectionStatus.Decode()) {
                ALOGE("%s, decode error", __func__);
            } else {
                sp<Connectivity> conn = Connectivity::getConnectivity(cookie);
                sp<IConnectivityCallback> callback = conn->getCallback();

                ESIMConnectionInformation esim;
                esim.networkInfo = static_cast<ESIMNetworkInfo>(data.status);
                if(data.m.hispeedfunPresent) {
                    esim.hispeedfun = static_cast<bool>(data.hispeedfun);
                }
                esim.networkAvailable = static_cast<bool>(data.networkavailable);
                esim.apnStatus = static_cast<APNStatus>(data.data);
                esim.operatorName = static_cast<ESIMOperatorStatus>(data.operator_);
                esim.signalCsqValue = static_cast<uint8_t>(data.signalstrength);
                esim.trafficData.rxbytecount = data.trafficdata.rxbytecount;
                esim.trafficData.txbytecount = data.trafficdata.txbytecount;
                if (data.m.ipadrPresent) {
                    ALOGI("%s, ip addr present", __func__);
                    esim.ipAddr = handleIpAddress(data.ipadr.numocts, data.ipadr.data);
                }

                if (callback != nullptr) {
                    auto ret = callback->onTcamESIMStaUpdateCallback(esim);
                    if(!ret.isOk()) {
                        ALOGE("%s, failed to notify client esimInfo", __func__);
                    }
                }
            }
            break;
        }
        case OP_TYPE_ERROR: {
            handleGenericError(packet, OP_ID_OpESIMConnectionStatus);
            break;
        }
        default:
            ALOGE("%s, unknown OP_ID_OpESIMConnectionStatus packets", __func__);
            break;
    }
}

void handleWLANMode(ipcp_packet_t *packet) {
    if (packet == nullptr) return;

    ipcp_header_t *header = &packet->header;
    uint16_t len = header->length - ASN_HEADER_LENGTH_OFFSET;

    switch (header->op_type) {
        case OP_TYPE_NOTIFICATION: {
            ASN1PERDecodeBuffer decodeBuffer((OSOCTET *)packet->payload, len, false);
            ASN1T_OpWLANMode_Notification data;

            ASN1C_OpWLANMode_Notification OpWLANMode_Notification(decodeBuffer, data);
            if (OpWLANMode_Notification.Decode()) {
                ALOGE("%s, decode error", __func__);
            } else {
                sp<Connectivity> conn = Connectivity::getConnectivity(cookie);
                sp<IConnectivityCallback> callback = conn->getCallback();

                if (callback != nullptr) {
                    callback->onTcamWifiModeCallback(static_cast<WLANMode>(data.functionalControl));
                }

                STA_state = WifiState::UNKNOWN;
                AP_state = SoftApState::UNKNOWN;
            }
            break;
        }
        case OP_TYPE_ERROR: {
            handleGenericError(packet, OP_ID_OpWLANMode);
            break;
        }
        default: {
            ALOGE("%s, unknown OP_ID_OpWLANMode packets", __func__);
            break;
        }
    }
}

void handleWLANModeReq(ipcp_packet_t *packet) {
    if (packet == nullptr) return;

    ipcp_header_t *header = &packet->header;
    uint16_t len = header->length - ASN_HEADER_LENGTH_OFFSET;

    switch (header->op_type) {
        case OP_TYPE_RESPONSE: {
            ASN1PERDecodeBuffer decodeBuffer((OSOCTET *)packet->payload, len, false);
            ASN1T_OpWLANModeReq_Response data;

            ASN1C_OpWLANModeReq_Response OpWLANModeReq_Response(decodeBuffer, data);
            if (OpWLANModeReq_Response.Decode()) {
                ALOGE("%s, decode error", __func__);
            } else {
                sp<Connectivity> conn = Connectivity::getConnectivity(cookie);
                sp<IConnectivityCallback> callback = conn->getCallback();

                if (callback != nullptr) {
                    callback->onTcamWifiModeCallback(static_cast<WLANMode>(data.functionalControl));
                }
            }
            break;
        }
        case OP_TYPE_ERROR: {
            handleGenericError(packet, OP_ID_OpWLANMode);
            break;
        }
        default: {
            ALOGE("%s, unknown OP_ID_OpWLANMode packets", __func__);
            break;
        }
    }
}

void handleWLANAPSetting(ipcp_packet_t * packet) {
    if (packet == nullptr) return;

    ipcp_header_t *header = &packet->header;
    uint16_t len = header->length - ASN_HEADER_LENGTH_OFFSET;

    switch (header->op_type) {
        case OP_TYPE_RESPONSE:
        case OP_TYPE_NOTIFICATION: {
            ASN1PERDecodeBuffer decodeBuffer((OSOCTET *)packet->payload, len, false);
            ASN1T_OpWLANAPSETTING_Response data;

            ASN1C_OpWLANAPSETTING_Response OpWLANAPSETTING_Response(decodeBuffer, data);
            if (OpWLANAPSETTING_Response.Decode()) {
                ALOGE("%s, decode error", __func__);
            } else {
                sp<Connectivity> conn = Connectivity::getConnectivity(cookie);
                sp<IConnectivityCallback> callback = conn->getCallback();

                WifiApConfigurationHAL ap_config;
                ap_config.band = static_cast<WifiBand>(data.frequencyBand);
                ap_config.feq = static_cast<Frequency>(data.frequencyChannel);
                ap_config.ssid = hidl_string(reinterpret_cast<const char*>(data.wl_AP_SSID));
                ap_config.psk = hidl_string(reinterpret_cast<const char*>(data.wl_AP_PASS));

                if (callback != nullptr) {
                    callback->onSoftApConfigChanged(ap_config);
                }
            }
            break;
        }
        case OP_TYPE_ERROR: {
            handleGenericError(packet, OP_ID_OpWLANAPSETTING);
            break;
        }
        default: {
            ALOGE("%s, unknown OP_ID_OpWLANAPSETTING packets", __func__);
            break;
        }
    }
}

void handleWLANAPConnDevList(ipcp_packet_t *packet) {
    if (packet == nullptr) return;

    ipcp_header_t *header = &packet->header;
    uint16_t len = header->length - ASN_HEADER_LENGTH_OFFSET;

    switch (header->op_type) {
        case OP_TYPE_RESPONSE: {
            ASN1PERDecodeBuffer decodeBuffer((OSOCTET *)packet->payload, len, false);
            ASN1T_OpWLANAPConnDevList_Response data;

            ASN1C_OpWLANAPConnDevList_Response OpWLANAPConnDevList_Response(decodeBuffer, data);
            if (OpWLANAPConnDevList_Response.Decode()) {
                ALOGE("%s, decode error", __func__);
            } else {
                sp<Connectivity> conn = Connectivity::getConnectivity(cookie);
                sp<IConnectivityCallback> callback = conn->getCallback();

                SoftApConnectedDevInfo ap_connected_info;
                ap_connected_info.band =static_cast<WifiBand>(data.frequencyBand);
                ap_connected_info.feq = static_cast<Frequency>(data.frequencyChannel);

                if (data.m.ap_ipadrPresent) {
                    ALOGI("%s, ip addr present", __func__);
                    ap_connected_info.ipAddr = handleIpAddress(data.ap_ipadr.numocts, data.ap_ipadr.data);
                }

                if (data.m.ap_MacadrPresent) {
                    for (uint32_t i = 0; i < data.ap_Macadr.numocts; i++ ) {
                        ap_connected_info.macAddr[i] = data.ap_Macadr.data[i];
                    }
                }

                ap_connected_info.ssid = hidl_string(reinterpret_cast<const char*>(data.wl_AP_SSID));

                std::vector<SoftApClient> client_list;
                ASN1C_OpWLANAPConnDevList_Response_connectedDevList asn1c_connectedDevice(data.connectedDevList);
                auto iterator = asn1c_connectedDevice.iterator();
                while (iterator->hasNext()) {
                    SoftApClient client;

                    auto dev_info = static_cast<ASN1T_CON_DEV_INFO *>(iterator->next());
                    client.devIpAddr = handleIpAddress(dev_info->dev_IP_adr.numocts, dev_info->dev_IP_adr.data);
                    client.devName = hidl_string(reinterpret_cast<const char*>(dev_info->dev_Name));
                    for (uint32_t node_n = 0; node_n < (dev_info->dev_Mac_adr.numocts); node_n++) {
                        client.macAddr[node_n] = dev_info->dev_Mac_adr.data[node_n];
                    }
                    client.status = static_cast<ConnectedStatus>(dev_info->conn_Status);

                    client_list.push_back(client);
                }

                ap_connected_info.connectedDevList = client_list;

                if (callback != nullptr) {
                   callback->onSoftApClientsChanged(ap_connected_info);
                }
            }

            break;
        }
        case OP_TYPE_NOTIFICATION: {
            ASN1PERDecodeBuffer decodeBuffer((OSOCTET *)packet->payload, len, false);
            ASN1T_OpWLANAPConnDevList_Notification data;

            ASN1C_OpWLANAPConnDevList_Notification OpWLANAPConnDevList_Notification(decodeBuffer, data);
            if (OpWLANAPConnDevList_Notification.Decode()) {
                ALOGE("%s, decode error", __func__);
            } else {
                sp<Connectivity> conn = Connectivity::getConnectivity(cookie);
                sp<IConnectivityCallback> callback = conn->getCallback();

                SoftApConnectedDevInfo ap_connected_info;
                ap_connected_info.band =static_cast<WifiBand>(data.frequencyBand);
                ap_connected_info.feq = static_cast<Frequency>(data.frequencyChannel);

                if (data.m.ap_ipadrPresent) {
                    ALOGI("%s, ip addr present", __func__);
                    ap_connected_info.ipAddr = handleIpAddress(data.ap_ipadr.numocts, data.ap_ipadr.data);
                }

                if (data.m.ap_MacadrPresent) {
                    for (uint32_t i = 0; i < data.ap_Macadr.numocts; i++ ) {
                        ap_connected_info.macAddr[i] = data.ap_Macadr.data[i];
                    }
                }

                ap_connected_info.ssid = hidl_string(reinterpret_cast<const char*>(data.wl_AP_SSID));

                std::vector<SoftApClient> client_list;
                ASN1C_OpWLANAPConnDevList_Notification_connectedDevList asn1c_connectedDevice(data.connectedDevList);
                auto iterator = asn1c_connectedDevice.iterator();
                while (iterator->hasNext()) {
                    SoftApClient client;

                    auto dev_info = static_cast<ASN1T_CON_DEV_INFO *>(iterator->next());
                    client.devIpAddr = handleIpAddress(dev_info->dev_IP_adr.numocts, dev_info->dev_IP_adr.data);
                    client.devName = hidl_string(reinterpret_cast<const char*>(dev_info->dev_Name));
                    for (uint32_t node_n = 0; node_n < (dev_info->dev_Mac_adr.numocts); node_n++) {
                        client.macAddr[node_n] = dev_info->dev_Mac_adr.data[node_n];
                    }
                    client.status = static_cast<ConnectedStatus>(dev_info->conn_Status);

                    client_list.push_back(client);
                }

                ap_connected_info.connectedDevList = client_list;

                if (callback != nullptr) {
                    callback->onSoftApClientsChanged(ap_connected_info);
                }

            }
            break;
        }
        case OP_TYPE_ERROR: {
            handleGenericError(packet, OP_ID_OpWLANAPConnDevList);
            break;
        }
        default: {
            ALOGE("%s, unknown OP_ID_OpWLANAPConnDevList packets", __func__);
            break;
        }
    }
}

void handleWLANSTAConnect(ipcp_packet_t * packet) {
    if (packet == nullptr) return;

    ipcp_header_t *header = &packet->header;
    uint16_t len = header->length - ASN_HEADER_LENGTH_OFFSET;

    switch (header->op_type) {
        case OP_TYPE_NOTIFICATION: {
            ASN1PERDecodeBuffer decodeBuffer((OSOCTET *)packet->payload, len, false);
            ASN1T_OpWLANSTAConnect_Notification data;

            ASN1C_OpWLANSTAConnect_Notification OpWLANSTAConnect_Notification(decodeBuffer, data);
            if (OpWLANSTAConnect_Notification.Decode()) {
                ALOGE("%s, decode error", __func__);
            } else {
                sp<Connectivity> conn = Connectivity::getConnectivity(cookie);
                sp<IConnectivityCallback> callback = conn->getCallback();

                STAConnectResult conn_result;
                conn_result.ssid = hidl_string(reinterpret_cast<const char*>(data.wl_AP_SSID));
                conn_result.connected = static_cast<ConnectedStatus>(data.connectedResult);
                ALOGD("%s, ori connected = %#x", __func__, data.connectedResult);
                ALOGD("%s, connected = %#x", __func__, conn_result.connected);
                ALOGD("%s, conn_result.ssid: %s", __func__, conn_result.ssid.c_str());
                if (data.m.failure_ReasonCodePresent) {
                    conn_result.failureReasonCode = data.failure_ReasonCode;
                    ALOGD("%s, failureReasonCode = %#x", __func__, data.failure_ReasonCode);
                }

                if (callback != nullptr) {
                     callback->onWifiConnectResult(conn_result);
                }
            }
            break;
        }
        case OP_TYPE_ERROR: {
            handleGenericError(packet, OP_ID_OpWLANSTAConnect);
            break;
        }
        default: {
            ALOGE("%s, unknown OP_ID_OpWLANSTAConnect packets", __func__);
            break;
        }
    }
}

void handleWLANSTAStatus(ipcp_packet_t *packet) {
    if (packet == nullptr) return;

    ipcp_header_t *header = &packet->header;
    uint16_t len = header->length - ASN_HEADER_LENGTH_OFFSET;

    switch (header->op_type) {
        case OP_TYPE_RESPONSE:
        case OP_TYPE_NOTIFICATION:
        case OP_TYPE_NOTIFICATION_CYCLIC: {
            ASN1PERDecodeBuffer decodeBuffer((OSOCTET *)packet->payload, len, false);
            ASN1T_OpWLANSTAStatus_Response data;

            ASN1C_OpWLANSTAStatus_Response OpWLANSTAStatus_Response(decodeBuffer, data);
            if (OpWLANSTAStatus_Response.Decode()) {
                ALOGE("%s, decode error", __func__);

                for (uint16_t i = 0; i < len; i++) {
                    ALOGE("%s, %#x", __func__, packet->payload[i]);
                }

            } else {
                sp<Connectivity> conn = Connectivity::getConnectivity(cookie);
                sp<IConnectivityCallback> callback = conn->getCallback();

                WLANSTAStatus status;
                status.band = WifiBand::BAND_UNSPECIFIED;
                if (data.m.sta_ipadrPresent) {
                    status.ipAddr = handleIpAddress(data.sta_ipadr.numocts, data.sta_ipadr.data);
                }

                if (data.m.sta_MacadrPresent) {
                    for (uint32_t i = 0; i < data.sta_Macadr.numocts; i++) {
                        status.macAddr[i] = data.sta_Macadr.data[i];
                        ALOGD("%s, macAddr[%#x] %#x", __func__, i, status.macAddr[i]);
                    }
                }

                if(data.m.avaliableNetworkPresent) {
                    std::vector<ScanResultHal> scan_results;

                    ScanResultHal scanHal;
                    auto ap_info = data.avaliableNetwork;

                    for (uint32_t j = 0; j < (ap_info.ap_Macadr.numocts); j++) {
                        scanHal.bssid[j] = ap_info.ap_Macadr.data[j];
                    }

                    scanHal.band = static_cast<WifiBand>(ap_info.frequencyBand);
                    scanHal.connStatus = static_cast<ConnectedStatus>(ap_info.conn_Status);
                    scanHal.feq = Frequency::CHANNEL_UNSPECIFIED;
                    scanHal.rssi = ap_info.rssi;
                    scanHal.secType = static_cast<SecurityType>(ap_info.sec_Type);
                    scanHal.ssid = hidl_string(reinterpret_cast<const char *>(ap_info.available_AP_SSID));

                    ALOGD("%s, before if scanHal.connStatus is %d ", __func__, static_cast<int>(scanHal.connStatus));
                    if (static_cast<int>(scanHal.connStatus)) {
                        scan_results.push_back(scanHal);
                        status.scanResults = scan_results;
                    }
                }

                if (callback != nullptr) {
                    auto ret = callback->onWifiConnectionChanged(status);
                    if(!ret.isOk()) {
                        ALOGE("%s, failed to notify client wifi connect status", __func__);
                    }
                }
            }
            break;
        }
        case OP_TYPE_ERROR: {
            handleGenericError(packet, OP_ID_OpWLANSTAStatus);
            break;
        }
        default: {
            ALOGE("%s, unknown OP_ID_OpWLANSTAStatus packets", __func__);
            break;
        }
    }
}

void handleRememberedNet(ipcp_packet_t *packet) {
    if (packet == nullptr) return;

    ipcp_header_t *header = &packet->header;
    uint16_t len = header->length - ASN_HEADER_LENGTH_OFFSET;

    switch (header->op_type) {
        case OP_TYPE_RESPONSE: {
            ASN1PERDecodeBuffer decodeBuffer((OSOCTET *)packet->payload, len, false);
            ASN1T_OpWLANSTARememberedNetwks_Response data;

            ASN1C_OpWLANSTARememberedNetwks_Response OpWLANSTARememberedNetwks_Response(decodeBuffer, data);
            if (OpWLANSTARememberedNetwks_Response.Decode()) {
                ALOGE("%s, decode error", __func__);
            } else {
                sp<Connectivity> conn = Connectivity::getConnectivity(cookie);
                sp<IConnectivityCallback> callback = conn->getCallback();

                RememberdNetworks remember_networks;
                std::vector<SavedNetwork> vector;

                ASN1C_OpWLANSTARememberedNetwks_Response_rememberedNetwork OpWLANSTARememberedNetwks(data.rememberedNetwork);
                auto iterator = OpWLANSTARememberedNetwks.iterator();

                while (iterator->hasNext()) {
                    SavedNetwork saved_network;

                    auto received_saved_network = static_cast<ASN1T_Remembered_AP_INFO *>(iterator->next());
                    saved_network.band = static_cast<WifiBand>(received_saved_network->frequencyBand);
                    saved_network.ssid = hidl_string(reinterpret_cast<const char *>(received_saved_network->available_AP_SSID));
                    saved_network.secType = static_cast<SecurityType>(received_saved_network->sec_Type);

                    vector.push_back(saved_network);
                }

                remember_networks.remembered_networks = vector;

                if (callback != nullptr) {
                    auto ret = callback->onRemberedNetworkChanged(remember_networks);
                    if(!ret.isOk()) {
                        ALOGE("%s, failed to notify client RemberedNetworkChanged", __func__);
                    }
                }
            }
            break;
        }
        case OP_TYPE_ERROR: {
            handleGenericError(packet, OP_ID_OpWLANSTARememberedNetwks);
            break;
        }
        default: {
            ALOGE("%s, unknown OP_ID_OpWLANSTARememberedNetwks packets", __func__);
            break;
        }
    }
}

void handleForgetNetworks(ipcp_packet_t *packet) {
    if (packet == nullptr) return;

    ipcp_header_t *header = &packet->header;
    uint16_t len = header->length - ASN_HEADER_LENGTH_OFFSET;

    switch (header->op_type) {
        case OP_TYPE_NOTIFICATION: {
            ASN1PERDecodeBuffer decodeBuffer((OSOCTET *)packet->payload, len, false);
            ASN1T_OpWLANSTAForgetRememberedNetwk_Notification data;

            ASN1C_OpWLANSTAForgetRememberedNetwk_Notification OpWLANSTAForgetRememberedNetwk_Notification(decodeBuffer, data);
            if (OpWLANSTAForgetRememberedNetwk_Notification.Decode()) {
                ALOGE("%s, decode error", __func__);
            } else {
                sp<Connectivity> conn = Connectivity::getConnectivity(cookie);
                sp<IConnectivityCallback> callback = conn->getCallback();

                if (callback != nullptr) {
                    callback -> onDisConAndForgetNetwkUpdateCallback(data.executionResult);
                }
            }
            break;
        }
        case OP_TYPE_ERROR: {
            handleGenericError(packet, OP_ID_OpWLANSTAForgetRememberedNetwk);
            break;
        }
        default: {
            ALOGE("%s, unknown OP_ID_OpWLANSTAForgetRememberedNetwk packets", __func__);
            break;
        }
    }
}

void handleScanResults(ipcp_packet_t *packet) {
    if (packet == nullptr) return;

    ipcp_header_t *header = &packet->header;
    uint16_t len = header->length - ASN_HEADER_LENGTH_OFFSET;

    switch (header->op_type) {
        case OP_TYPE_RESPONSE:
        case OP_TYPE_NOTIFICATION: {
            ASN1PERDecodeBuffer decodeBuffer((OSOCTET *)packet->payload, len, false);
            ASN1T_OpWLANSTAScan_Response data;

            ASN1C_OpWLANSTAScan_Response OpWLANSTAScan_Response(decodeBuffer, data);
            if (OpWLANSTAScan_Response.Decode()) {
                ALOGE("%s, decode error", __func__);
            } else {
                sp<Connectivity> conn = Connectivity::getConnectivity(cookie);
                sp<IConnectivityCallback> callback = conn->getCallback();

                CurrentScanResults current_scan_results;
                std::vector<ScanResultHal> vector;

                ASN1C_OpWLANSTAScan_Response_scanResults response_scanResults(data.scanResults);
                auto iterator = response_scanResults.iterator();

                while (iterator->hasNext()) {
                    ScanResultHal scan_hal_result;

                    auto ap_info = static_cast<ASN1T_Current_AP_INFO *>(iterator->next());
                    scan_hal_result.band = static_cast<WifiBand>(ap_info->frequencyBand);

                    ALOGI("%s, ap_MacAddrPresent is %#x", __func__, ap_info->m.ap_MacadrPresent);
                    if (ap_info->m.ap_MacadrPresent) {
                        uint32_t count = ap_info->ap_Macadr.numocts;
                        ALOGD("%s, ap Mac Addr Numb: %d", __func__, count);

                        for (uint32_t j = 0; j < count; j++) {
                            scan_hal_result.bssid[j] = ap_info->ap_Macadr.data[j];
                            ALOGD("%s, bssid[%#x] is %#x", __func__, j, scan_hal_result.bssid[j]);
                        }
                    }

                    // Maybe change later...
                    scan_hal_result.feq = Frequency::CHANNEL_UNSPECIFIED;
                    scan_hal_result.rssi = ap_info->rssi;
                    scan_hal_result.secType = static_cast<SecurityType>(ap_info->sec_Type);
                    scan_hal_result.ssid = hidl_string(reinterpret_cast<const char *>(ap_info->available_AP_SSID));

                    ALOGD("%s, new scan result entry: %s", __func__, reinterpret_cast<const char *>(ap_info->available_AP_SSID));

                    vector.push_back(scan_hal_result);
                }
                current_scan_results.scanResults = vector;

                if (callback != nullptr) {
                    auto ret = callback->onWifiScanResultsAvailable(current_scan_results);
                    if(!ret.isOk()) {
                        ALOGE("%s, failed to notify client scan result", __func__);
                    }
                }
            }
            break;
        }
        case OP_TYPE_ERROR: {
            handleGenericError(packet, OP_ID_OpWLANSTAScan);
            break;
        }
        default: {
            ALOGE("%s, unknown OP_ID_OpWLANSTAScan packets", __func__);
            break;
        }
    }
}

void handleTcamLogSettingReq(ipcp_packet_t *packet) {
    if (packet == nullptr) return;

    ipcp_header_t *header = &packet->header;
    uint16_t len = header->length - ASN_HEADER_LENGTH_OFFSET;

    switch (header->op_type) {
        case OP_TYPE_RESPONSE: {
            ASN1PERDecodeBuffer decodeBuffer((OSOCTET *)packet->payload, len, false);
            ASN1T_OpWLANLogSettingReq_Response data;

            ASN1C_OpWLANLogSettingReq_Response OpWLANLogSettingReq_Response(decodeBuffer, data);
            if (OpWLANLogSettingReq_Response.Decode()) {
                ALOGE("%s, decode error", __func__);
            } else {
                sp<Connectivity> conn = Connectivity::getConnectivity(cookie);
                sp<IConnectivityCallback> callback = conn->getCallback();

                if (callback != nullptr) {
                    callback->onTcamWLANLogSetUpdateCallback(data.switch_Mode);
                }
            }
            break;
        }
        case OP_TYPE_ERROR: {
            handleGenericError(packet, OP_ID_OpWLANLogSettingReq);
            break;
        }
        default: {
            ALOGE("%s, unknown OP_ID_OpWLANLogSettingReq packets", __func__);
            break;
        }
    }
}


void handleTcamLogSetting(ipcp_packet_t *packet) {
    if (packet == nullptr) return;

    ipcp_header_t *header = &packet->header;
    uint16_t len = header->length - ASN_HEADER_LENGTH_OFFSET;

    switch (header->op_type) {
        case OP_TYPE_NOTIFICATION: {
            ASN1PERDecodeBuffer decodeBuffer((OSOCTET *)packet->payload, len, false);
            ASN1T_OpWLANLOGSETTING_Notification data;

            ASN1C_OpWLANLOGSETTING_Notification OpWLANLOGSETTING_Notification(decodeBuffer, data);
            if (OpWLANLOGSETTING_Notification.Decode()) {
                ALOGE("%s, decode error", __func__);
            } else {
                sp<Connectivity> conn = Connectivity::getConnectivity(cookie);
                sp<IConnectivityCallback> callback = conn->getCallback();

                if (callback != nullptr) {
                    callback->onTcamWLANLogSetUpdateCallback(data.switch_Mode);
                }
            }
            break;
        }
        case OP_TYPE_ERROR: {
            handleGenericError(packet, OP_ID_OpWLANLOGSETTING);
            break;
        }
        default: {
            ALOGE("%s, unknown OP_ID_OpWLANLOGSETTING packets", __func__);
            break;
        }
    }
}

void handleTcamInformation(ipcp_packet_t *packet) {
    if (packet == nullptr) return;

    ipcp_header_t *header = &packet->header;
    uint16_t len = header->length - ASN_HEADER_LENGTH_OFFSET;

    switch (header->op_type) {
        case OP_TYPE_RESPONSE: {
            ASN1PERDecodeBuffer decodeBuffer((OSOCTET *)packet->payload, len, false);
            ASN1T_SyncTCAMinformation_Response data;

            ASN1C_SyncTCAMinformation_Response SyncTCAMinformation_Response(decodeBuffer, data);
            if (SyncTCAMinformation_Response.Decode()) {
                ALOGE("%s, decode error", __func__);
            } else {
                sp<Connectivity> conn = Connectivity::getConnectivity(cookie);
                sp<IConnectivityCallback> callback = conn->getCallback();

                TCAMInformation info;
                info.delivery_partNumber = hidl_string(data.dU);
                info.hwSD_HWKN = hidl_string(data.hWSD_HWKN);
                info.sXBL = hidl_string(data.sXBL);
                info.sXDI = hidl_string(data.sXDI_SXBL);
                //info.sWBL = hidl_string(data.sWBL);
                info.sWDI_SWBL = hidl_string(data.sWDI_SWBL);
                info.sWLM_SWLx = hidl_string(data.sWLM_SWLx);
                info.sXDI_SWLM = hidl_string(data.sXDI_SWLM);
                info.iMSI = hidl_string(data.iMSI);
                info.iCCID = hidl_string(data.iCCID);
                info.mSISDN = hidl_string(data.mSISDN);
                info.iMEI = hidl_string(data.iMEI);
                info.tCAMID = hidl_string(data.tCAMID);

                if (callback != nullptr) {
                    callback->onTcamInfoUpdateCallback(info);
                }
            }
            break;
        }
        case OP_TYPE_ERROR: {
            handleGenericError(packet, OP_ID_SyncTCAMinformation);
            break;
        }
        default: {
            ALOGE("%s, unknown OP_ID_SyncTCAMinformation packets", __func__);
            break;
        }
    }
}

void handleWifiDisconnectRes(ipcp_packet_t *packet) {
    if (packet == nullptr) return;

    ipcp_header_t *header = &packet->header;
    uint16_t len = header->length - ASN_HEADER_LENGTH_OFFSET;

    switch (header->op_type) {
        case OP_TYPE_ERROR: {
            handleGenericError(packet, OP_ID_OpWLANSTADisCon);
            break;
        }
        default: {
            ALOGE("%s, unknown OP_ID_OpWLANSTADisCon packets", __func__);
            break;
        }
    }
}

void handleTestConnectionStatusInfo(ipcp_packet_t *packet) {
    if (packet == nullptr) return;

    ipcp_header_t *header = &packet->header;
    uint16_t len = header->length - ASN_HEADER_LENGTH_OFFSET;

    switch (header->op_type) {
        case OP_TYPE_NOTIFICATION: {
            ASN1PERDecodeBuffer decodeBuffer((OSOCTET *)packet->payload, len, false);
            ASN1T_OpTestConnectionStatus_Notification data;

            ASN1C_OpTestConnectionStatus_Notification TestConnectionStatus_Notification(decodeBuffer, data);
            if (TestConnectionStatus_Notification.Decode()) {
                ALOGE("%s, decode error", __func__);
            } else {
                sp<Connectivity> conn = Connectivity::getConnectivity(cookie);
                sp<IConnectivityCallback> callback = conn->getCallback();

                TestConnStatusInfo info;

                info.vin = hidl_string(data.vin);
                info.temID = hidl_string(data.temID);

                if(data.m.tcamDtcTestStatusPresent) {
                    info.tcamDtcTestInfo.tcamDtcStatus =  static_cast<bool>(data.tcamDtcTestStatus.tcamDtcStatus);

                    if(data.tcamDtcTestStatus.m.tcamDtcListPresent) {
                        std::vector<TcamDtcInfo> dtc_list;
                        ASN1C_TcamDtcTestStatus_tcamDtcList asn1c_tcamDtcList(data.tcamDtcTestStatus.tcamDtcList);
                        auto iterator1 = asn1c_tcamDtcList.iterator();
                        while(iterator1->hasNext()) {
                            TcamDtcInfo dtcInfo;

                            auto received_dtcInfo = static_cast<ASN1T_TcamDtcInfo *>(iterator1->next());
                            dtcInfo.dtc_Code = hidl_string(received_dtcInfo->dtc_Code);
                            dtcInfo.dtc_Code_Value = hidl_string(received_dtcInfo->dtc_Code_Value);

                            dtc_list.push_back(dtcInfo);
                        }
                        info.tcamDtcTestInfo.tcamDtcList = dtc_list;
                    }
                }

                if(data.m.tcamDtcTestStatusPresent) {
                    info.simTestInfo.simStatus =  static_cast<bool>(data.simTestStatus.simStatus);

                    if(data.simTestStatus.m.simCardInfoPresent) {
                        info.simTestInfo.simCardInfo.simIMSI = hidl_string(data.simTestStatus.simCardInfo.simIMSI);
                        info.simTestInfo.simCardInfo.simICCID = hidl_string(data.simTestStatus.simCardInfo.simICCID);
                        info.simTestInfo.simCardInfo.simMSISDN = hidl_string(data.simTestStatus.simCardInfo.simMSISDN);
                        info.simTestInfo.simCardInfo.simIMEI = hidl_string(data.simTestStatus.simCardInfo.simIMEI);
                    }
                }

                if(data.m.connectTestStatusPresent) {
                    info.connectTestInfo.connectStatus = static_cast<bool>(data.connectTestStatus.connectStatus);

                    if(data.connectTestStatus.m.connectInfoListPresent) {
                        std::vector<ConnectInfo> connInfoList;
                        ASN1C_ConnectTestStatus_connectInfoList asn1c_connInfoList(data.connectTestStatus.connectInfoList);
                        auto iterator2 = asn1c_connInfoList.iterator();
                        while(iterator2->hasNext()) {
                            ConnectInfo connInfo;

                            auto received_connInfo = static_cast<ASN1T_ConnectInfo *>(iterator2->next());
                            connInfo.connUrl = hidl_string((char *)received_connInfo->conn_url);
                            connInfo.packetLoss = static_cast<uint16_t>(received_connInfo->packetloss);
                            connInfo.responseTime = static_cast<uint16_t>(received_connInfo->responsetime);
                            connInfo.connStatus = static_cast<bool>(received_connInfo->conn_Status);

                            connInfoList.push_back(connInfo);
                        }
                        info.connectTestInfo.connectInfoList = connInfoList;
                    }
                }

                if(data.m.networkTestStatusPresent) {
                    info.networkTestInfo.networkStatus = static_cast<bool>(data.networkTestStatus.networkStatus);

                    if(data.networkTestStatus.m.networkinfoPresent) {
                        auto netInfo = info.networkTestInfo.networkinfo;
                        auto dataNetInfo = data.networkTestStatus.networkinfo;

                        if(data.networkTestStatus.networkinfo.m.simCardInfoPresent) {
                            netInfo.simCardInfo.simIMSI = hidl_string(dataNetInfo.simCardInfo.simIMSI);
                            netInfo.simCardInfo.simICCID = hidl_string(dataNetInfo.simCardInfo.simICCID);
                            netInfo.simCardInfo.simMSISDN = hidl_string(dataNetInfo.simCardInfo.simMSISDN);
                            netInfo.simCardInfo.simIMEI = hidl_string(dataNetInfo.simCardInfo.simIMEI);
                        }

                        if(data.networkTestStatus.networkinfo.m.simConStatusPresent) {
                            netInfo.simConStatus = static_cast<ESIMNetworkInfo>(dataNetInfo.simConStatus);
                        }
                        if(data.networkTestStatus.networkinfo.m.simOperatorStatusPresent) {
                            netInfo.simOperatorStatus = static_cast<ESIMOperatorStatus>(dataNetInfo.simOperatorStatus);
                        }
                        if(data.networkTestStatus.networkinfo.m.lteModePresent) {
                            netInfo.lteMode = static_cast<LTEMode>(dataNetInfo.lteMode);
                        }
                        if(data.networkTestStatus.networkinfo.m.ipadrPresent) {
                            netInfo.ipAddr = handleIpAddress(dataNetInfo.ipadr.numocts, dataNetInfo.ipadr.data);
                        }
                        if(data.networkTestStatus.networkinfo.m.rssnrPresent) {
                            netInfo.rssnr = static_cast<uint8_t>(dataNetInfo.rssnr);
                        }
                        if(data.networkTestStatus.networkinfo.m.rsrpPresent) {
                            netInfo.rsrp = static_cast<uint16_t>(dataNetInfo.rsrp);
                        }
                        if(data.networkTestStatus.networkinfo.m.rsrqPresent) {
                            netInfo.rsrq = static_cast<int8_t>(dataNetInfo.rsrq);
                        }
                        if(data.networkTestStatus.networkinfo.m.rssiPresent) {
                            netInfo.rssi = static_cast<int8_t>(dataNetInfo.rssi);
                        }
                        if(data.networkTestStatus.networkinfo.m.mccPresent) {
                            netInfo.mcc = hidl_string(dataNetInfo.mcc);
                        }
                        if(data.networkTestStatus.networkinfo.m.mncPresent) {
                            netInfo.mnc = hidl_string(dataNetInfo.mnc);
                        }
                        if(data.networkTestStatus.networkinfo.m.pciPresent) {
                            netInfo.pci = static_cast<uint16_t>(dataNetInfo.pci);
                        }
                        if(data.networkTestStatus.networkinfo.m.earfcnPresent) {
                            netInfo.earfcn = static_cast<uint16_t>(dataNetInfo.earfcn);
                        }
                        if(data.networkTestStatus.networkinfo.m.earfcnPresent) {
                            netInfo.tac = static_cast<uint32_t>(dataNetInfo.tac);
                        }
                        if(data.networkTestStatus.networkinfo.m.lacPresent) {
                            netInfo.lac = static_cast<uint16_t>(dataNetInfo.lac);
                        }
                    }
                }

                if(data.m.callTestStatusPresent) {
                    info.callTestInfo.callStatus = static_cast<bool>(data.callTestStatus.callStatus);
                }

                if(data.m.smsTestStatusPresent) {
                    info.smsTestInfo.smsStatus = static_cast<bool>(data.smsTestStatus.smsStatus);
                    info.smsTestInfo.smsreceipt = static_cast<bool>(data.smsTestStatus.smsreceipt);
                }

                if(data.m.gpsInfoPresent) {
                    info.gpsInfo.longitude = static_cast<int32_t>(data.gpsInfo.longitude);
                    info.gpsInfo.latitude = static_cast<int32_t>(data.gpsInfo.latitude);
                }

                if (callback != nullptr) {
                    callback-> OnTestConnStatusInfoCallback(info);
                }
            }

            break;
        }
        case OP_TYPE_ERROR: {
            handleGenericError(packet, OP_ID_TestConnectionStatus);
            break;
        }
        default: {
            ALOGE("%s, unknown OP_ID_TestConnectionStatus packets", __func__);
            break;
        }
    }

}

void handleNetworkConnectionStatusInfo(ipcp_packet_t *packet) {
    if (packet == nullptr) return;

    ipcp_header_t *header = &packet->header;
    uint16_t len = header->length - ASN_HEADER_LENGTH_OFFSET;

    switch (header->op_type)
    {
        case OP_TYPE_NOTIFICATION_CYCLIC: {
            ASN1PERDecodeBuffer decodeBuffer((OSOCTET *)packet->payload, len, false);
            ASN1T_OpNetworkConnectionStatus_NotificationCyclic data;

            ASN1C_OpNetworkConnectionStatus_NotificationCyclic OpNetworkConnectionStatus(decodeBuffer, data);
            if(OpNetworkConnectionStatus.Decode()) {
                ALOGE("%s, decode error", __func__);
            } else {
                sp<Connectivity> conn = Connectivity::getConnectivity(cookie);
                sp<IConnectivityCallback> callback = conn->getCallback();

                NetworkConnectionStatusInfo NetConnInfo;
                NetConnInfo.pubNetAvail = static_cast<bool>(data.publicnetworkavailable);
                NetConnInfo.priNetAvail = static_cast<bool>(data.privatenetworkavailable);
                ALOGD("%s, pubNetAvail is %d", __func__, NetConnInfo.pubNetAvail);
                ALOGD("%s, priNetAvail is %d", __func__, NetConnInfo.priNetAvail);
                if(callback != nullptr)
                    callback->OnNetConnStatusInfoCallback(NetConnInfo);
            }
            break;
        }
        case OP_TYPE_ERROR: {
            handleGenericError(packet, OP_ID_NetworkConnectionStatus);
            break;
        }
        default: {
            ALOGE("%s, unknown OP_ID_NetworkConnectionStatus packets", __func__);
            break;
        }
    }
}

void handle5GMode(ipcp_packet_t *packet) {
    ALOGE("%s, handle5GMode", __func__);
    if (packet == nullptr) return;

    ipcp_header_t *header = &packet->header;
    uint16_t len = header->length - ASN_HEADER_LENGTH_OFFSET;

    switch (header->op_type)
    {
        case OP_TYPE_RESPONSE: {
            ALOGE("%s, OP_TYPE_RESPONSE", __func__);
            ASN1PERDecodeBuffer decodeBuffer((OSOCTET *)packet->payload, len, false);
            ASN1T_Op5GModeReq_Response data;

            ASN1C_Op5GModeReq_Response Op5GModeReq_Response(decodeBuffer, data);
            if (Op5GModeReq_Response.Decode()) {
                ALOGE("%s, decode error", __func__);
            } else {
                sp<Connectivity> conn = Connectivity::getConnectivity(cookie);
                sp<IConnectivityCallback> callback = conn->getCallback();

                uint32_t mode = data.functionalControl;
                ALOGE("%s, handle5GMode %d", __func__, mode);
                if (callback != nullptr) {
                    callback->On5GModeCallback(mode == 1 ? true : false);
                }
            }
            break;
        }
        case OP_TYPE_ERROR: {
            ALOGE("%s, OP_TYPE_ERROR", __func__);
            handleGenericError(packet, OP_ID_5GModeReq);
            break;
        }
        default: {
            ALOGE("%s, unknown OP_ID_5GModeReq packets", __func__);
            break;
        }
    }
}

void handleSet5GMode(ipcp_packet_t *packet) {
    ALOGE("%s, handleSet5GMode", __func__);
    if (packet == nullptr) return;

    ipcp_header_t *header = &packet->header;
    uint16_t len = header->length - ASN_HEADER_LENGTH_OFFSET;

    switch (header->op_type)
    {
        case OP_TYPE_RESPONSE: {
            ALOGE("%s, OP_TYPE_RESPONSE", __func__);
            ASN1PERDecodeBuffer decodeBuffer((OSOCTET *)packet->payload, len, false);
            ASN1T_OpSet5GMode_Response data;

            ASN1C_OpSet5GMode_Response OpSet5GMode_Response(decodeBuffer, data);
            if (OpSet5GMode_Response.Decode()) {
                ALOGE("%s, decode error", __func__);
            } else {
                sp<Connectivity> conn = Connectivity::getConnectivity(cookie);
                sp<IConnectivityCallback> callback = conn->getCallback();

                uint32_t mode = data.functionalControl;
                ALOGE("%s, handleSet5GMode %d", __func__, mode);
                if (callback != nullptr) {
                    callback->On5GModeCallback(mode == 1 ? true : false);
                }
            }
            break;
        }
        case OP_TYPE_ERROR: {
            ALOGE("%s, OP_TYPE_ERROR", __func__);
            handleGenericError(packet, OP_ID_Set5GMode);
            break;
        }
        default: {
            ALOGE("%s, unknown OP_ID_Set5GMode packets", __func__);
            break;
        }
    }
}

void wifi_ipcp_cb(ipcp_packet_t *packet, ipcp_peer_t peer)
{
    ipcp_header_t *header = &packet->header;

    ALOGV("<-------------------------------------------------------------------->");
    ALOGV("<--------------connecitivty receive package info--------------------->");
    ALOGV("%s, received ipcp header : sid: %#x, op_id: %#x, op_type: %#x", __func__,
                header->service_id, header->operation_id, header->op_type);
    ALOGV("<-------------------------------------------------------------------->");

    if (header->service_id != SERVICE_ID_CONNECTIVITY) {
        ALOGE("%s, invalid service id %hu detected !!!\n", __func__, header->service_id);
        return;
    }

    switch (header->operation_id) {
        case OP_ID_OpESIMConnectionStatus:
            handleESIMConnectionStatus(packet);
            break;
        case OP_ID_OpWLANMode:
            handleWLANMode(packet);
            break;
        case OP_ID_OpWLANAPSETTING:
            handleWLANAPSetting(packet);
            break;
        case OP_ID_OpWLANAPConnDevList:
            handleWLANAPConnDevList(packet);
            break;
        case OP_ID_OpWLANSTAConnect:
            handleWLANSTAConnect(packet);
            break;
        case OP_ID_OpWLANSTAStatus:
            handleWLANSTAStatus(packet);
            break;
        case OP_ID_OpWLANSTARememberedNetwks:
            handleRememberedNet(packet);
            break;
        case OP_ID_OpWLANSTAForgetRememberedNetwk:
            handleForgetNetworks(packet);
            break;
        case OP_ID_OpWLANSTAScan:
            handleScanResults(packet);
            break;
        case OP_ID_OpWLANLOGSETTING:
            handleTcamLogSetting(packet);
            break;
        case OP_ID_SyncTCAMinformation:
            handleTcamInformation(packet);
            break;
        case OP_ID_OpWLANModeReq:
            handleWLANModeReq(packet);
            break;
        case OP_ID_OpWLANLogSettingReq:
            handleTcamLogSettingReq(packet);
            break;
        case OP_ID_OpWLANSTADisCon:
            handleWifiDisconnectRes(packet);
            break;
        case OP_ID_TestConnectionStatus:
            handleTestConnectionStatusInfo(packet);
            break;
        case OP_ID_NetworkConnectionStatus:
            handleNetworkConnectionStatusInfo(packet);
            break;
        case OP_ID_5GModeReq:
            handle5GMode(packet);
            break;
        case OP_ID_Set5GMode:
            handleSet5GMode(packet);
            break;
        default:
            ALOGE("%s, unknown operation ID: %hu", __func__, header->operation_id);
            return;
    }

}

void Connectivity::setup_wifi_ipcp() {
    if(Connectivity::mIpcpThread.joinable()) {
        ALOGI("setupIpcp start call mIpcpThread.join()");
        Connectivity::mIpcpThread.join();
    }

    Connectivity::mIpcpThread = std::thread([this]() {
        ipcp_transport_conf_t client_config;
        ipcp_stack_err_t error_code;
        init_ipcp_config(&client_config);
        ALOGV("Connectivity wifi setup ipcp");
        while(true) {
            error_code = ipcp_setup_with_opids(client_config, &wifi_ipcp_callbacks, Connectivity_OperationIDs, 17);
            if (error_code != 0)
            {
                ALOGE("Connectivity ipcp setup error: %d", error_code);
                std::this_thread::sleep_for(std::chrono::milliseconds(2000));
            }
            else
            {
                ALOGV("Connectivity ipcp setup success");
                break;
            }
        }
        setupVehicle();
    });
    Connectivity::mIpcpThread.detach();
}

std::function<void(int)>generic_request_lamba = [](uint32_t op_id) {
    const char * content = nullptr;
    int stat, len;
    ipcp_stack_err_t err;
    bool trace = false;

    ASN1PEREncodeBuffer encodeBuffer(false);
    ASN1C_OpGeneric_Request OpGeneric_RequestPDU(encodeBuffer);

    if ((stat = OpGeneric_RequestPDU.Encode()) == 0) {
        if (trace) {
            ALOGV("Encoding was successful\n");
            ALOGV("Hex dump of encoded record:\n");
            encodeBuffer.hexDump();
            ALOGV("Binary dump:\n");
            encodeBuffer.binDump("Data");
        }
        len = encodeBuffer.getMsgLen();
        content = (char *)encodeBuffer.getMsgPtr();
        ipcp_packet_t *packet = build_ipcp_packet(SERVICE_ID_CONNECTIVITY,
                        op_id, OP_TYPE_REQUEST, IPCP_DATA_ENCODED,(void *)content, len);
        if ((err = ipcp_send(wifi_tcam_ipcp_peer, packet)) != STACK_SEND_MSG_SUCCESS) {
            ALOGE("%s: ipcp_send err : %d", __FUNCTION__, err);
        }
    } else {
        ALOGE("OpGeneric_RequestPDU encode failed\n");
        encodeBuffer.printErrorInfo();
    }
};

Return<StatusCode> Connectivity::queryCurrentWifiMode()
{
    ALOGD("%s", __func__);
    mThread.schedule(std::bind(generic_request_lamba, OP_ID_OpWLANModeReq), common_delay);
    return StatusCode::SUCCESS;
}


Return<StatusCode> Connectivity::setWifiEnabled(bool enabled)
{
    ALOGD("%s, set STA WIFI [ON/OFF] %d\n", __func__, enabled);
    auto task = [enabled]() {
        const char *content = nullptr;
        int stat, len;
        ipcp_stack_err_t err;
        bool trace = false;

        enum {
            noWLAN = 1,
            accessPointOn = 2,
            staOn = 3,
            reserved = 4
        };

        ASN1PEREncodeBuffer encodeBuffer(false);
        ASN1T_OpWLANMode_SetRequestNoReturn data;

        if (enabled) {
            data.functionalControl = staOn;
            STA_state = WifiState::ENABLING;
        } else {
            data.functionalControl = noWLAN;
            STA_state = WifiState::DISABLING;
        }

        ASN1C_OpWLANMode_SetRequestNoReturn OpWLANMode_SetReqNoReturn(encodeBuffer, data);

        if ((stat = OpWLANMode_SetReqNoReturn.Encode()) == 0) {
            if (trace) {
                ALOGV("Encoding was successful\n");
                ALOGV("Hex dump of encoded record:\n");
                encodeBuffer.hexDump();
                ALOGV("Binary dump:\n");
                encodeBuffer.binDump("Data");
            }
            len = encodeBuffer.getMsgLen();
            content = (char *)encodeBuffer.getMsgPtr();
            ipcp_packet_t *packet = build_ipcp_packet(SERVICE_ID_CONNECTIVITY,
                            OP_ID_OpWLANMode, IPCP_OPERATION_SETREQUEST_NORETURN, IPCP_DATA_ENCODED,(void *)content, len);
            if ((err = ipcp_send(wifi_tcam_ipcp_peer, packet)) != STACK_SEND_MSG_SUCCESS) {
                ALOGE("%s: ipcp_send err : %d", __FUNCTION__, err);
            }
        } else {
            ALOGE("OpWLANMode_SetReqNoReturn encode failed\n");
            encodeBuffer.printErrorInfo();
        }
    };
    mThread.schedule(task, common_delay);
    return StatusCode::SUCCESS;
}

Return<StatusCode> Connectivity::setWifiAPEnabled(bool enabled)
{
    ALOGD("%s, set SoftAP [ON/OFF] %d\n", __func__, enabled);
    auto task = [enabled]() {
        const char *content = nullptr;
        int stat, len;
        ipcp_stack_err_t err;
        bool trace = false;

        enum {
            noWLAN = 1,
            accessPointOn = 2,
            staOn = 3,
            reserved = 4
        } ;

        ASN1PEREncodeBuffer encodeBuffer(false);
        ASN1T_OpWLANMode_SetRequestNoReturn data;

        if (enabled) {
            data.functionalControl = accessPointOn;
            AP_state = SoftApState::ENABLING;
        } else {
            data.functionalControl = noWLAN;
            AP_state = SoftApState::DISABLING;
        }

        ASN1C_OpWLANMode_SetRequestNoReturn OpWLANMode_SetReqNoReturn(encodeBuffer, data);

        if ((stat = OpWLANMode_SetReqNoReturn.Encode()) == 0) {
            if (trace) {
                ALOGV("Encoding was successful\n");
                ALOGV("Hex dump of encoded record:\n");
                encodeBuffer.hexDump();
                ALOGV("Binary dump:\n");
                encodeBuffer.binDump("Data");
            }
            len = encodeBuffer.getMsgLen();
            content = (char *)encodeBuffer.getMsgPtr();
            ipcp_packet_t *packet = build_ipcp_packet(SERVICE_ID_CONNECTIVITY,
                            OP_ID_OpWLANMode, IPCP_OPERATION_SETREQUEST_NORETURN, IPCP_DATA_ENCODED,(void *)content, len);
            if ((err = ipcp_send(wifi_tcam_ipcp_peer, packet)) != STACK_SEND_MSG_SUCCESS)
            {
                ALOGE("%s: ipcp_send err : %d", __FUNCTION__, err);
            }
        } else {
            ALOGE("OpWLANMode_SetReqNoReturn encode failed\n");
            encodeBuffer.printErrorInfo();
        }
    };
    mThread.schedule(task, common_delay);
    return StatusCode::SUCCESS;
}

Return<StatusCode> Connectivity::startScan() {
    ALOGD("%s", __func__);

    mThread.schedule(std::bind(generic_request_lamba, OP_ID_OpWLANSTAScan), common_delay);
    return StatusCode::SUCCESS;
}

Return<StatusCode> Connectivity::queryRememberedNetworks() {
    ALOGD("%s", __func__);
    mThread.schedule(std::bind(generic_request_lamba, OP_ID_OpWLANSTARememberedNetwks), common_delay);
    return StatusCode::SUCCESS;
}

Return<StatusCode> Connectivity::queryCurrentWifiStatus() {
    ALOGD("%s", __func__);
    mThread.schedule(std::bind(generic_request_lamba, OP_ID_OpWLANSTAStatus), common_delay);
    return StatusCode::SUCCESS;
}

Return<StatusCode> Connectivity::connectNetwork(const WifiConfigurationHAL& config)
{
    ALOGD("%s", __func__);

    auto task = [config]() {
        const char *content = nullptr;
        int stat, len;
        ipcp_stack_err_t err;
        bool trace = true;

        ASN1PEREncodeBuffer encodeBuffer(false);
        ASN1T_OpWLANSTAConnect_SetRequestNoReturn data;

        string default_passwd = "unknow_ecarx_yinhaiwanxiang";
        if (default_passwd.compare(config.psk.c_str()) == 0) {
            data.m.wl_AP_PASSPresent = 0;
        } else {
            data.m.wl_AP_PASSPresent = 1;
        }

        data.wl_AP_SSID = (OSUTF8CHAR*)config.ssid.c_str();
        data.wl_AP_PASS = (OSUTF8CHAR*)config.psk.c_str();
        data.sec_Type = (ASN1T_Security_Type)config.secType;
        ALOGV("%s, data.wl_AP_PASS is %s",  __func__, data.wl_AP_PASS);
        ALOGV("%s, data.wl_AP_SSID is %s", __func__, data.wl_AP_SSID);
        ALOGV("%s, data.sec_Type is %d", __func__, data.sec_Type);


        ASN1C_OpWLANSTAConnect_SetRequestNoReturn OpWLANConnect_SetRequestNoReturn(encodeBuffer, data);
        if ((stat = OpWLANConnect_SetRequestNoReturn.Encode()) == 0) {
            if (trace) {
                ALOGV("Encoding was successful\n");
                ALOGV("Hex dump of encoded record:\n");
                encodeBuffer.hexDump();
                ALOGV("Binary dump:\n");
                encodeBuffer.binDump("Data");
            }
            len = encodeBuffer.getMsgLen();
            content = (char *)encodeBuffer.getMsgPtr();
            ipcp_packet_t *packet = build_ipcp_packet(SERVICE_ID_CONNECTIVITY,
                            OP_ID_OpWLANSTAConnect, IPCP_OPERATION_SETREQUEST_NORETURN, IPCP_DATA_ENCODED,(void *)content, len);
            if ((err = ipcp_send(wifi_tcam_ipcp_peer, packet)) != STACK_SEND_MSG_SUCCESS)
            {
                ALOGE("%s: ipcp_send err : %d", __FUNCTION__, err);
            }
        } else {
            ALOGE("OpWLANConnect_SetRequestNoReturn encode failed\n");
            encodeBuffer.printErrorInfo();
        }
    };

    mThread.schedule(task, common_delay);
    return StatusCode::SUCCESS;
}

Return<StatusCode> Connectivity::disconnectNetwork(const hidl_string& ssid)
{
    ALOGD("%s", __func__);

    auto task = [ssid]() {
        const char *content = nullptr;
        int stat, len;
        ipcp_stack_err_t err;
        bool trace = false;

        ASN1PEREncodeBuffer encodeBuffer(false);
        ASN1T_OpWLANSTADisCon_SetRequestNoReturn data;

        data.wl_AP_SSID = (OSUTF8CHAR*)ssid.c_str();

        ASN1C_OpWLANSTADisCon_SetRequestNoReturn OpWLANSTADisCon_SetRequestNoReturn(encodeBuffer, data);
        if ((stat = OpWLANSTADisCon_SetRequestNoReturn.Encode()) == 0) {
            if (trace) {
                ALOGV("Encoding was successful\n");
                ALOGV("Hex dump of encoded record:\n");
                encodeBuffer.hexDump();
                ALOGV("Binary dump:\n");
                encodeBuffer.binDump("Data");
            }
            len = encodeBuffer.getMsgLen();
            content = (char *)encodeBuffer.getMsgPtr();
            ipcp_packet_t *packet = build_ipcp_packet(SERVICE_ID_CONNECTIVITY,
                            OP_ID_OpWLANSTADisCon, IPCP_OPERATION_SETREQUEST_NORETURN, IPCP_DATA_ENCODED,(void *)content, len);
            if ((err = ipcp_send(wifi_tcam_ipcp_peer, packet)) != STACK_SEND_MSG_SUCCESS)
            {
                ALOGE("%s: ipcp_send err : %d", __FUNCTION__, err);
            }
        } else {
            ALOGE("OpWLANSTADisCon_SetRequestNoReturn encode failed\n");
            encodeBuffer.printErrorInfo();
        }
    };

    mThread.schedule(task, common_delay);
    return StatusCode::SUCCESS;
}

Return<StatusCode> Connectivity::forgetNetwork(const SavedNetwork& network)
{
    ALOGD("%s", __func__);

    auto task = [network]() {
        const char *content = nullptr;
        int stat, len;
        ipcp_stack_err_t err;
        bool trace = false;

        ASN1PEREncodeBuffer encodeBuffer(false);
        ASN1T_OpWLANSTAForgetRememberedNetwk_SetRequestNoReturn data;

        data.wl_AP_SSID = (OSUTF8CHAR *)network.ssid.c_str();
        data.sec_Type = (ASN1T_Security_Type)network.secType;

        ASN1C_OpWLANSTAForgetRememberedNetwk_SetRequestNoReturn OpWLANSTAForgetRememberedNetwk_SetRequestNoReturn(encodeBuffer, data);
        if ((stat = OpWLANSTAForgetRememberedNetwk_SetRequestNoReturn.Encode()) == 0) {
            if (trace) {
                ALOGV("Encoding was successful\n");
                ALOGV("Hex dump of encoded record:\n");
                encodeBuffer.hexDump();
                ALOGV("Binary dump:\n");
                encodeBuffer.binDump("Data");
            }
            len = encodeBuffer.getMsgLen();
            content = (char *)encodeBuffer.getMsgPtr();
            ipcp_packet_t *packet = build_ipcp_packet(SERVICE_ID_CONNECTIVITY,
                            OP_ID_OpWLANSTAForgetRememberedNetwk, IPCP_OPERATION_SETREQUEST_NORETURN, IPCP_DATA_ENCODED,(void *)content, len);
            if ((err = ipcp_send(wifi_tcam_ipcp_peer, packet)) != STACK_SEND_MSG_SUCCESS)
            {
                ALOGE("%s: ipcp_send err : %d", __FUNCTION__, err);
            }
        } else {
            ALOGE("OpWLANConnect_SetRequestNoReturn encode failed\n");
            encodeBuffer.printErrorInfo();
        }
    };

    mThread.schedule(task, common_delay);
    return StatusCode::SUCCESS;
}

Return<StatusCode> Connectivity::setWifiApConfiguration(const WifiApConfigurationHAL& ap_config)
{
    ALOGD("%s", __func__);
    auto task = [ap_config]() {
        const char *content = nullptr;
        int stat, len;
        ipcp_stack_err_t err;
        bool trace = false;

        ASN1PEREncodeBuffer encodeBuffer(false);
        ASN1T_OpWLANAPSETTING_SetRequest data;

        data.m.wl_AP_SSIDPresent = 1;

        string default_passwd = "unknow_ecarx_yinhaiwanxiang";
        if (default_passwd.compare(ap_config.psk.c_str()) == 0) {
            data.m.wl_AP_PASSPresent = 0;
        } else {
            data.m.wl_AP_PASSPresent = 1;
        }

        data.m.frequencyBandPresent = 1;
        data.m.frequencyChannelPresent = 0;

        data.wl_AP_SSID = (OSUTF8CHAR *)ap_config.ssid.c_str();
        data.wl_AP_PASS = (OSUTF8CHAR *)ap_config.psk.c_str();
        data.frequencyBand = (OSUINT8)ap_config.band;
        data.frequencyChannel = (OSUINT8)ap_config.feq;

        ASN1C_OpWLANAPSETTING_SetRequest OpWLANAPSETTING_SetRequest(encodeBuffer, data);
        if ((stat = OpWLANAPSETTING_SetRequest.Encode()) == 0) {
            if (trace) {
                ALOGV("Encoding was successful\n");
                ALOGV("Hex dump of encoded record:\n");
                encodeBuffer.hexDump();
                ALOGV("Binary dump:\n");
                encodeBuffer.binDump("Data");
            }
            len = encodeBuffer.getMsgLen();
            content = (char *)encodeBuffer.getMsgPtr();
            ipcp_packet_t *packet = build_ipcp_packet(SERVICE_ID_CONNECTIVITY,
                            OP_ID_OpWLANAPSETTING, IPCP_OPERATION_SETREQUEST_NORETURN, IPCP_DATA_ENCODED,(void *)content, len);
            if ((err = ipcp_send(wifi_tcam_ipcp_peer, packet)) != STACK_SEND_MSG_SUCCESS)
            {
                ALOGE("%s: ipcp_send err : %d", __FUNCTION__, err);
            }
        } else {
            ALOGE("OpWLANAPSETTING_SetRequest encode failed\n");
            encodeBuffer.printErrorInfo();
        }
    };

    mThread.schedule(task, common_delay);
    return StatusCode::SUCCESS;
}

Return<StatusCode> Connectivity::queryCurrentApConfiguration()
{
    ALOGD("%s", __func__);
    mThread.schedule(std::bind(generic_request_lamba, OP_ID_OpWLANAPSETTING), common_delay);
    return StatusCode::SUCCESS;
}

Return<StatusCode> Connectivity::queryWifiApConnectedDevs()
{
    ALOGD("%s", __func__);
    mThread.schedule(std::bind(generic_request_lamba, OP_ID_OpWLANAPConnDevList), common_delay);
    return StatusCode::SUCCESS;
}

Return<StatusCode> Connectivity::queryCurrentTcamLogSettings()
{
    ALOGD("%s", __func__);
    mThread.schedule(std::bind(generic_request_lamba, OP_ID_OpWLANLogSettingReq), common_delay);
    return StatusCode::SUCCESS;
}

Return<StatusCode> Connectivity::setTcamWlanLogSettings(bool enabled) {
    auto task = [enabled]() {
        const char *content = nullptr;
        int stat, len;
        ipcp_stack_err_t err;
        bool trace = false;

        ASN1PEREncodeBuffer encodeBuffer(false);
        ASN1T_OpWLANLOGSETTING_SetRequestNoReturn data;

        data.switch_Mode = (OSBOOL)enabled;

        ASN1C_OpWLANLOGSETTING_SetRequestNoReturn OpWLANLOGSETTING_SetRequestNoReturn(encodeBuffer, data);

        if ((stat = OpWLANLOGSETTING_SetRequestNoReturn.Encode()) == 0) {
            if (trace) {
                ALOGV("Encoding was successful\n");
                ALOGV("Hex dump of encoded record:\n");
                encodeBuffer.hexDump();
                ALOGV("Binary dump:\n");
                encodeBuffer.binDump("Data");
            }
            len = encodeBuffer.getMsgLen();
            content = (char *)encodeBuffer.getMsgPtr();
            ipcp_packet_t *packet = build_ipcp_packet(SERVICE_ID_CONNECTIVITY,
                            OP_ID_OpWLANLOGSETTING, IPCP_OPERATION_SETREQUEST_NORETURN, IPCP_DATA_ENCODED,(void *)content, len);
            if ((err = ipcp_send(wifi_tcam_ipcp_peer, packet)) != STACK_SEND_MSG_SUCCESS)
            {
                ALOGE("%s: ipcp_send err : %d", __FUNCTION__, err);
            }
        } else {
            ALOGE("OpWLANLOGSETTING_SetRequestNoReturn encode failed\n");
            encodeBuffer.printErrorInfo();
        }
    };
    mThread.schedule(task, common_delay);
    return StatusCode::SUCCESS;
}

Return<StatusCode> Connectivity::queryTcamSyncInformation() {
    ALOGD("%s", __func__);

    mThread.schedule(std::bind(generic_request_lamba, OP_ID_SyncTCAMinformation), common_delay);
    return StatusCode::SUCCESS;
}

Return<StatusCode> Connectivity::testCurrentConnectionStatus() {
    ALOGD("%s", __func__);

    auto task = []() {
         ipcp_stack_err_t err;

         ipcp_packet_t *packet = build_ipcp_packet(SERVICE_ID_CONNECTIVITY,
                         OP_ID_TestConnectionStatus, IPCP_OPERATION_SETREQUEST_NORETURN, IPCP_DATA_ENCODED, NULL, 0);
         if((err = ipcp_send(wifi_tcam_ipcp_peer, packet)) != STACK_SEND_MSG_SUCCESS)
         {
            ALOGE("%s: ipcp send err : %d", __FUNCTION__, err);
         }
    };
    mThread.schedule(task, common_delay);
    return StatusCode::SUCCESS;
}

Return<StatusCode> Connectivity::set5GMode(bool enabled) {
    ALOGD("%s, set FiveG MODE [ON/OFF] %d\n", __func__, enabled);
    auto task = [enabled]() {
        const char *content = nullptr;
        int stat, len;
        ipcp_stack_err_t err;
        bool trace = false;

        enum {
            fiveGModeOn = 1, // On
            fiveGModeOff = 2 // Off
        };

        ASN1PEREncodeBuffer encodeBuffer(false);
        ASN1T_OpSet5GMode_SetRequest data;

        if (enabled) {
            data.functionalControl = fiveGModeOn;
        } else {
            data.functionalControl = fiveGModeOff;
        }
        ALOGD("%s, set FiveG MODE data.functionalControl %d\n", __func__, data.functionalControl);
        ASN1C_OpSet5GMode_SetRequest OpSet5GMode_SetRequest(encodeBuffer, data);

        if ((stat = OpSet5GMode_SetRequest.Encode()) == 0) {
            if (trace) {
                ALOGV("Encoding was successful\n");
                ALOGV("Hex dump of encoded record:\n");
                encodeBuffer.hexDump();
                ALOGV("Binary dump:\n");
                encodeBuffer.binDump("Data");
            }

            len = encodeBuffer.getMsgLen();
            content = (char *)encodeBuffer.getMsgPtr();
            ipcp_packet_t *packet = build_ipcp_packet(SERVICE_ID_CONNECTIVITY,
                            OP_ID_Set5GMode, IPCP_OPERATION_SETREQUEST, IPCP_DATA_ENCODED,(void *)content, len);
            if ((err = ipcp_send(wifi_tcam_ipcp_peer, packet)) != STACK_SEND_MSG_SUCCESS) {
                ALOGE("%s: ipcp_send err : %d", __FUNCTION__, err);
            }
        } else {
          ALOGE("OpSet5GMode_SetRequest encode failed\n");
          encodeBuffer.printErrorInfo();
      }
    };
    mThread.schedule(task, common_delay);
    return StatusCode::SUCCESS;
}

Return<StatusCode> Connectivity::req5GMode() {
    ALOGD("%s", __func__);

    mThread.schedule(std::bind(generic_request_lamba, OP_ID_5GModeReq), common_delay);
    return StatusCode::SUCCESS;
}


} // implementation
} // V1_0
} // connectivity
} // xma
} // ecarx
} // vendor
